#pragma once

#include <iostream>
#include "Connection.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"
#include <signal.h>
using namespace Protocol;
using namespace CalculateNs;
class HandlerConnection{
public:

//处理
    static void HandlerRequestion(Connection* conn)
    {
        std::string& buffer = conn->InBuffer();
        Factory factory;
        Calculate calculate;

        auto req = factory.BuildRequest();//生成请求
        std::string message;
        while(Decode(buffer,&message))//将buffer中的数据切分出来！
        {
            bool ret = req->DeSerialize(message);//将切割出来的数据进行反序列
            if(ret)
            {   
                auto resp = calculate.Cal(req);
                
                string responsestr;

                resp->Serialize(&responsestr);//序列化
                Encode(responsestr);//加报头
                conn->AddOutBuffer(responsestr);//放进 输出缓冲区中
            }   
            else{
                continue;//如果失败就继续读取
            }         
        }
        //到达此处表示数据已经放到了缓冲区中
        if(!conn->OutBufferEmpty())//不为空表示有数据，直接发
            conn->_sender(conn);
    }

    static void Recver(Connection* conn)
    {

        
        errno = 0;

        char buffer[1024];
        while(1)
        {
            ssize_t n  = recv(conn->SockFD(),buffer,sizeof(buffer)-1,0);//0 非阻塞读取
            if(n > 0)
            {
                // std::cout << "recv------------------------------" << std::endl;

                buffer[n] = 0;//将c读取到的最后一个字符放上\0代表终止，形成字符串 
                conn->AddBuffer(buffer);//将读取到的数据放进输入缓冲区
                // std::cout << "AddBuffer------------------------------" << std::endl;

            }
            else{
                // std::cout << "AddBuffer------------------------------" << std::endl;

                if(errno == EAGAIN) break;//数据读完了！
                else if(errno == EINTR) continue;//被中断了，继续读
                else{
                    //到此处才是真正的出错了！
                    conn->_excepter(conn);//调用异常处理机制
                    return;
                }
            }
        }
        //到达此处就读取到来所有数据
        HandlerRequestion(conn);//处理数据

    }


    static void Sender(Connection* conn)
    {
        errno = 0;

        std::string& outbuffer = conn->OutBuffer();
        while(1)
        {
            // std::cout << outbuffer << std::endl;
            ssize_t n = send(conn->SockFD(),outbuffer.c_str(),outbuffer.size(),0);
            if(n >= 0)
            {
                outbuffer.erase(0,n);
                // std::cout << outbuffer << std::endl;

                if(outbuffer.empty())
                    return;
            }
            else{
                if(errno == EAGAIN)  break;
                    //缓冲区满了，需要break
                else if(errno == EINTR) continue;
                else{
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        //走出这里就表示本轮发送缓冲区已经满了，没办法在继续写进去，所以就需要对该连接开启 关心 写事件 ， 这样当发生缓冲区内的数据被 上传到网络中后，缓冲区就就空了，就能再次继续写！

        //添加写关心
        if(!conn->OutBuffer().empty())
        {
            //不为空，就表示满了！

            //添加对连接 添加写事件
            conn->_R->EnableReadWrite(conn->SockFD(),true,true);
        }
    }

    static void Excepter(Connection* conn)
    {

        lg.LogMessage(Info,"connection arase done,who：%d\n",conn->SockFD());
        errno = 0;
        conn->_R->RemoveConnection(conn->SockFD());
        conn->Close();
        delete conn;
    }

};